﻿namespace LeagueUtils
{
    using System;
    //using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.IO;


    /*
     * This class is thanks to Krashan, who is the developer of Yaric.
     */
    public class IniBinParser
    {
        private static uint item1Key = 0x45aa7e8;
        private static uint item2Key = 0x45aa7e9;
        private static uint item3Key = 0x45aa7ea;
        private static uint item4Key = 0x45aa7eb;
        private static uint item5Key = 0x45aa7ec;
        private static uint item6Key = 0x45aa7ed;
        private static uint itemAvailable = 0x45b1121c;
        private static uint itemImage = 0xff0b13f5;
        private byte[] m_Buffer;
        private int m_BufferIndex;
        private int m_BufferLength;
        private static int[] SegmentSizes = new int[] { 4, 4, 1, 2, 1, -1, 0, 0, 0, 0, 4, 0, 2, 0, 0, 0 };
        private static uint tagsKey = 0xf723bec1;

        public IniBinParser(byte[] buffer) : this(buffer, 0, buffer.Length)
        {
        }

        public IniBinParser(byte[] buffer, int index, int length)
        {
            this.m_Buffer = buffer;
            this.m_BufferIndex = index;
            this.m_BufferLength = length;
        }

        private void ApplyItemCode(byte[] buffer, int segmentType, int valueOffset, int dataOffset, int item)
        {
            if (segmentType == 3)
            {
                Array.Copy(BitConverter.GetBytes((ushort) item), 0, buffer, valueOffset, 2);
            }
            else if (segmentType == 12)
            {
                Array.Copy(Encoding.ASCII.GetBytes(item.ToString("0000")), 0, buffer, dataOffset, 4);
            }
        }

        private bool ExtractBool(byte[] buffer, int segmentType, int valueOffset, int dataOffset, int bitNumber)
        {
            if (segmentType == 5)
            {
                return ((buffer[valueOffset] & (((int) 1) << bitNumber)) != 0);
            }
            if (segmentType == 12)
            {
                int num;
                bool flag;
                if (int.TryParse(ExtractString(buffer, dataOffset), out num))
                {
                    return (num != 0);
                }
                if (bool.TryParse(ExtractString(buffer, dataOffset), out flag))
                {
                    return flag;
                }
            }
            return false;
        }

        private static string ExtractString(byte[] buffer, int dataOffset)
        {
            int count = StringLength(buffer, dataOffset);
            return Encoding.ASCII.GetString(buffer, dataOffset, count);
        }

        public byte[] returnByteArray()
        {
            return m_Buffer;
        }

        /*public string GetChampionTags()
        {
            string result = string.Empty;
            ProcessIniBin(this.m_Buffer, this.m_BufferIndex, this.m_BufferLength, delegate (byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber) {
                if (key == tagsKey)
                {
                    string temp1 = ExtractString(buffer, dataOffset);
                    string []temp2 = temp1.Split(new char[] { ',', ';' });
                    result = temp2.ToString();//string.Join(",", ExtractString(buffer, dataOffset).Split(new char[] { ',', ';' }).Convert<string, string>(s => s.Trim()).ToArray<string>());
                }
            });
            return result;
        }*/

        public string GetItemImageName()
        {
            string result = string.Empty;
            ProcessIniBin(this.m_Buffer, this.m_BufferIndex, this.m_BufferLength, delegate (byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber) {
                if (key == itemImage)
                {
                    result = ExtractString(buffer, dataOffset);
                }
            });
            return result;
        }

        public int[] GetRecommendedItems()
        {
            int[] result = new int[6];
            ProcessIniBin(this.m_Buffer, this.m_BufferIndex, this.m_BufferLength, delegate (byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber) {
                if (key == item1Key)
                    result[0] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
                if (key == item2Key)
                    result[1] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
                if (key == item3Key)
                    result[2] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
                if (key == item4Key)
                    result[3] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
                if (key == item5Key)
                    result[4] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
                if (key == item6Key)
                    result[5] = ParseItemCode(buffer, segmentType, valueOffset, dataOffset);
            });
            return result;
        }

        public bool IsItemAvailable()
        {
            bool result = false;
            ProcessIniBin(this.m_Buffer, this.m_BufferIndex, this.m_BufferLength, delegate (byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber) {
                if (key == itemAvailable)
                {
                    result = this.ExtractBool(buffer, segmentType, valueOffset, dataOffset, bitNumber);
                }
            });
            return result;
        }

        private static int ParseItemCode(byte[] buffer, int segmentType, int valueOffset, int dataOffset)
        {
            int result = 0;
            if (segmentType == 3)
            {
                return BitConverter.ToInt16(buffer, valueOffset);
            }
            if ((segmentType == 12) && (StringLength(buffer, dataOffset) == 4))
            {
                int.TryParse(Encoding.ASCII.GetString(buffer, dataOffset, 4), out result);
            }
            return result;
        }

        private static void ProcessIniBin(byte[] buffer, int bufferStart, int bufferLength, IniBinProcessor ProcessValue)
        {
            byte num1 = buffer[bufferStart];
            ushort num = BitConverter.ToUInt16(buffer, bufferStart + 1);
            ushort num2 = BitConverter.ToUInt16(buffer, bufferStart + 3);
            int startIndex = bufferStart + 5;
            for (int i = 0; num2 != 0; i++)
            {
                if ((num2 & 1) != 0)
                {
                    int num5 = BitConverter.ToUInt16(buffer, startIndex);
                    int num6 = SegmentSizes[i];
                    int num7 = num5 * 4;
                    int num8 = (num6 == -1) ? ((num5 + 7) / 8) : (num5 * num6);
                    for (int j = 0; j < num5; j++)
                    {
                        int num10 = (startIndex + 2) + (j * 4);
                        uint key = BitConverter.ToUInt32(buffer, num10);
                        int num12 = ((startIndex + 2) + num7) + ((num6 == -1) ? (j / 8) : (j * num6));
                        int dataOffset = -1;
                        int bitNumber = -1;
                        switch (i)
                        {
                            case 5:
                                bitNumber = j % 8;
                                break;

                            case 12:
                            {
                                ushort num15 = BitConverter.ToUInt16(buffer, num12);
                                dataOffset = ((bufferStart + bufferLength) - num) + num15;
                                break;
                            }
                        }
                        if (ProcessValue != null)
                        {
                            ProcessValue(buffer, i, key, num12, dataOffset, bitNumber);
                        }
                    }
                    startIndex += (2 + num7) + num8;
                }
                num2 = (ushort) (num2 >> 1);
            }
        }

        public void SetRecommendedItems(int[] items)
        {
            ProcessIniBin(this.m_Buffer, this.m_BufferIndex, this.m_BufferLength, delegate (byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber) {
                if (key == item1Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[0]);
                if (key == item2Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[1]);
                if (key == item3Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[2]);
                if (key == item4Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[3]);
                if (key == item5Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[4]);
                if (key == item6Key)
                    this.ApplyItemCode(buffer, segmentType, valueOffset, dataOffset, items[5]);
            });
        }

        private static int StringLength(byte[] buffer, int dataOffset)
        {
            int num = 0;
            while (buffer[dataOffset + num] != 0)
            {
                num++;
            }
            return num;
        }

        public delegate void IniBinProcessor(byte[] buffer, int segmentType, uint key, int valueOffset, int dataOffset, int bitNumber);
    }
}

